using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Collections.Generic;

using SBPweb.Themes.Windows.Schemes;
using TD.SandDock;

namespace SBPweb.Controls.Windows.Docking
{
    public class CustomRenderer : TD.SandDock.Rendering.Office2007Renderer
    {

        #region Private fields

        private Scheme pScheme;
        private Dictionary<Guid, DockControl> dictControls = new Dictionary<Guid, DockControl>();

        private bool pIsCDDocumentStrip = false;
        private event EventHandler<DrawCustomDocumentStripEventArgs> pOnCDDocumentStrip;
        private bool pIsCDTitleBar = false;
        private event EventHandler<DrawCustomTitleBarEventArgs> pOnCDTitleBar;

        #endregion

        #region Constructor logic

        public CustomRenderer(Scheme scheme)
            : base()
        {
            pScheme = scheme;

            this.CustomColors = true;

            this.Background = pScheme.Colors.BackgroundLight;

            this.DocumentContainerBackground = pScheme.Blends.Background;

            this.DocumentNormalTabBackground = pScheme.Blends.DocumentNormalTab;
            this.DocumentNormalTabInnerBorder = pScheme.Colors.ControlMid;
            this.DocumentNormalTabOuterBorder = pScheme.Colors.ContainerLight;

            this.DocumentHotTabBackground = pScheme.Blends.DocumentHotTab;
            this.DocumentHotTabInnerBorder = pScheme.Colors.ControlLight;
            this.DocumentHotTabOuterBorder = pScheme.Colors.ContainerMid;

            this.DocumentSelectedTabBackground = pScheme.Blends.DocumentSelectedTab;
            this.DocumentSelectedTabInnerBorder = pScheme.Colors.BackgroundMid;
            this.DocumentSelectedTabOuterBorder = pScheme.Colors.BackgroundMid;

            this.ActiveTitleBarBackground = pScheme.Blends.DocumentNormalTab;
            this.InactiveTitleBarBackground = pScheme.Blends.DocumentNormalTab;

            this.CollapsedTabHorizontalBackground = pScheme.Blends.DocumentNormalTab;
            this.CollapsedTabVerticalBackground = pScheme.Blends.DocumentNormalTab;

            this.TabStripSelectedTabBackground = pScheme.Blends.DocumentNormalTab;

            this.OnCustomDrawDocumentStrip += new EventHandler<DrawCustomDocumentStripEventArgs>(DrawCustomDocumentStrip);
        }

        #endregion

        #region Event handlers

        public event EventHandler<DrawCustomDocumentStripEventArgs> OnCustomDrawDocumentStrip
        {
            add
            {
                pOnCDDocumentStrip += value;
                pIsCDDocumentStrip = pOnCDDocumentStrip.GetInvocationList().Length != 0;
            }
            remove
            {
                pOnCDDocumentStrip -= value;
                pIsCDDocumentStrip = pOnCDDocumentStrip.GetInvocationList().Length != 0;
            }
        }

        public event EventHandler<DrawCustomTitleBarEventArgs> OnCustomDrawTitleBar
        {
            add
            {
                pOnCDTitleBar += value;
                pIsCDTitleBar = pOnCDDocumentStrip.GetInvocationList().Length != 0;
            }
            remove
            {
                pOnCDTitleBar -= value;
                pIsCDTitleBar = pOnCDDocumentStrip.GetInvocationList().Length != 0;
            }
        }

        #endregion

        #region Property accessors

        public Scheme CurrentScheme
        {
            get
            {
                return pScheme;
            }
        }

        public bool IsOnlyCustomDrawDocumentStrip
        {
            get
            {
                return pIsCDDocumentStrip;
            }
            set
            {
                pIsCDDocumentStrip = value;
            }
        }

        public bool IsOnlyCustomDrawTitleBar
        {
            get
            {
                return pIsCDTitleBar;
            }
            set
            {
                pIsCDTitleBar = value;
            }
        }

        #endregion

        #region Methods

        public void AssingNewManager(TD.SandDock.SandDockManager manager)
        {
            manager.Renderer = this;
            manager.DockControlAdded += new TD.SandDock.DockControlEventHandler(manager_DockControlAdded);
            manager.DockControlRemoved += new TD.SandDock.DockControlEventHandler(manager_DockControlRemoved);
        }

        void manager_DockControlAdded(object sender, TD.SandDock.DockControlEventArgs e)
        {
            lock (dictControls)
            {
                Guid g = e.DockControl.Guid;
                if (!dictControls.ContainsKey(g))
                {
                    dictControls.Add(g, e.DockControl);
                }
            }
        }

        void manager_DockControlRemoved(object sender, TD.SandDock.DockControlEventArgs e)
        {
            lock (dictControls)
            {
                Guid g = e.DockControl.Guid;
                if (dictControls.ContainsKey(g))
                {
                    dictControls.Remove(g);
                }
            }
        }

        protected override void DrawDockContainerBackground(Graphics graphics, TD.SandDock.DockContainer container, Rectangle bounds)
        {
            graphics.FillRectangle(new SolidBrush(Background), bounds);
        }

        protected override void DrawDocumentClientBackground(Graphics graphics, Rectangle bounds, Color backColor)
        {
            graphics.FillRectangle(new SolidBrush(backColor), bounds);
        }

        protected override Size MeasureDocumentStripTab(Graphics graphics, Image image, string text, Font font, DrawItemState state)
        {
            font = pScheme.Fonts.DocumentTitleBar;
            text = text.ToUpper();

            #region !!! DIRTY HACK DUE TO A MISSING FEATURE IN SANDDOCK !!!

            /*
            string phrase = "#DISABLED#";
            if (text.StartsWith(phrase))
            {
                text = text.Replace(phrase, string.Empty);
            }
            */
            if (text.Contains("{"))
            {
                text = ExtractGuid(text).Key;
            }

            #endregion

            return base.MeasureDocumentStripTab(graphics, image, text, font, state);
        }

        protected override void DrawDocumentStripTab(Graphics graphics, Rectangle bounds, Rectangle contentBounds, Image image, string text, Font font, Color backColor, Color foreColor, DrawItemState state, bool drawSeparator)
        {
            font = pScheme.Fonts.DocumentTitleBar;
            text = text.ToUpper();
            if ((state & DrawItemState.Selected) == DrawItemState.Selected)
            {
                foreColor = Color.White;
            }
            else
            {
                foreColor = Color.Black;
            }

            #region !!! DIRTY HACK DUE TO A MISSING FEATURE IN SANDDOCK !!!

            Guid guid = Guid.Empty;
            if (text.Contains("{"))
            {
                KeyValuePair<string, Guid> kvp = ExtractGuid(text);
                text = kvp.Key;
                guid = kvp.Value;
            }

            #endregion

            if (!pIsCDDocumentStrip)
            {
                base.DrawDocumentStripTab(graphics, bounds, contentBounds, image, string.Empty, font, Color.Transparent, Color.Transparent, state, drawSeparator);
                int x = contentBounds.Left + DocumentTabExtra + 4 + ((image == null) ? (0) : (image.Width + 4));
                int y = contentBounds.Top + 4;
                graphics.DrawString(text, font, new SolidBrush(foreColor), x, y);
            }

            #region !!! DIRTY HACK DUE TO A MISSING FEATURE IN SANDDOCK !!!

            if (guid != Guid.Empty)
            {
                DockControl dc = null;
                lock (dictControls)
                {
                    if (!dictControls.ContainsKey(guid))
                    {
                        return;
                    }
                    dc = dictControls[guid];
                }
                if (pOnCDDocumentStrip != null)
                {
                    DrawCustomDocumentStripEventArgs dcdsea = new DrawCustomDocumentStripEventArgs(dc, graphics, bounds, contentBounds, image, text, font, backColor, foreColor, state, drawSeparator);
                    pOnCDDocumentStrip(this, dcdsea);
                }
            }

            #endregion

        }

        protected override void DrawTitleBarText(Graphics graphics, Rectangle bounds, bool focused, string text, Font font)
        {
            #region !!! DIRTY HACK DUE TO A MISSING FEATURE IN SANDDOCK !!!

            Guid guid = Guid.Empty;
            if (text.Contains("{"))
            {
                KeyValuePair<string, Guid> kvp = ExtractGuid(text);
                text = kvp.Key;
                guid = kvp.Value;
            }

            #endregion

            font = pScheme.Fonts.ToolStripTitleBar;
            text = text.ToUpper();

            if (!pIsCDTitleBar)
            {
                base.DrawTitleBarText(graphics, bounds, focused, text, font);
            }

            #region !!! DIRTY HACK DUE TO A MISSING FEATURE IN SANDDOCK !!!

            if (guid != Guid.Empty)
            {
                DockControl dc = null;
                lock (dictControls)
                {
                    if (!dictControls.ContainsKey(guid))
                    {
                        return;
                    }
                    dc = dictControls[guid];
                }
                if (pOnCDTitleBar != null)
                {
                    DrawCustomTitleBarEventArgs dctbea = new DrawCustomTitleBarEventArgs(dc, graphics, bounds, focused, text, font);
                    pOnCDTitleBar(this, dctbea);
                }
            }

            #endregion
        }

        #endregion

        #region Private helper methods

        private void DrawCustomDocumentStrip(object sender, DrawCustomDocumentStripEventArgs e)
        {
            if (e.DockControl.Enabled == false)
            {
                Color c = Color.FromArgb(128, Background);
                e.Graphics.FillRectangle(new SolidBrush(c), e.ContentBounds.Left + 1, e.ContentBounds.Top, e.ContentBounds.Width - 2, e.ContentBounds.Height - 1);
            }
        }

        #endregion

        #region Static helper methods

        public static KeyValuePair<string, Guid> ExtractGuid(string text)
        {
            string[] split = text.Split(new char[] { '{', '}'}, StringSplitOptions.None );
            if (split.Length > 1)
            {
                try
                {
                    Guid g = new Guid(split[1]);
                    return new KeyValuePair<string, Guid>(split[0], g);
                }
                catch
                {
                }
            }
            return new KeyValuePair<string,Guid>(text, Guid.Empty);
        }

        public static string ImplodeGuid(KeyValuePair<string, Guid> kvp)
        {
            return kvp.Key + "{" + kvp.Value.ToString() + "}";
        }

        #endregion

        #region EventArgs

        public class DrawCustomDocumentStripEventArgs : PaintEventArgs
        {

            #region Private fields

            private DockControl pDockControl;
            private Rectangle pBounds;
            private Rectangle pContentBounds;
            private Image pImage;
            private string pText;
            private Font pFont;
            private Color pBackColor;
            private Color pForeColor;
            private DrawItemState pState;
            private bool pDrawSeparator;

            #endregion

            #region Constructor logic

            public DrawCustomDocumentStripEventArgs(DockControl dockControl, Graphics graphics, Rectangle bounds, Rectangle contentBounds, Image image, string text, Font font, Color backColor, Color foreColor, DrawItemState state, bool drawSeparator)
                : base(graphics, bounds)
            {
                pBackColor = backColor;
                pBounds = bounds;
                pContentBounds = contentBounds;
                pDockControl = dockControl;
                pDrawSeparator = drawSeparator;
                pFont = font;
                pForeColor = foreColor;
                pImage = image;
                pState = state;
                pText = text;
            }

            #endregion

            #region Property accessors

            public DockControl DockControl
            {
                get
                {
                    return pDockControl;
                }
            }

            public Rectangle Bounds
            {
                get
                {
                    return pBounds;
                }
            }

            public Rectangle ContentBounds
            {
                get
                {
                    return pContentBounds;
                }
            }

            public Image Image
            {
                get
                {
                    return pImage;
                }
            }

            public string Text
            {
                get
                {
                    return pText;
                }
            }

            public Font Font
            {
                get
                {
                    return pFont;
                }
            }

            public Color BackColor
            {
                get
                {
                    return pBackColor;
                }
            }

            public Color ForeColor
            {
                get
                {
                    return pForeColor;
                }
            }

            public DrawItemState State
            {
                get
                {
                    return pState;
                }
            }

            public bool DrawSeparator
            {
                get
                {
                    return pDrawSeparator;
                }
            }

            #endregion

        }

        public class DrawCustomTitleBarEventArgs : PaintEventArgs
        {

            #region Private fields

            private DockControl pDockControl;
            private Rectangle pBounds;
            private string pText;
            private Font pFont;
            private bool pFocused;

            #endregion

            #region Constructor logic

            public DrawCustomTitleBarEventArgs(DockControl dockControl, Graphics graphics, Rectangle bounds, bool focused, string text, Font font)
                : base(graphics, bounds)
            {
                pBounds = bounds;
                pDockControl = dockControl;
                pFocused = focused;
                pFont = font;
                pText = text;
            }

            #endregion


            #region Property accessors

            public DockControl DockControl
            {
                get
                {
                    return pDockControl;
                }
            }

            public Rectangle Bounds
            {
                get
                {
                    return pBounds;
                }
            }

            public string Text
            {
                get
                {
                    return pText;
                }
            }

            public Font Font
            {
                get
                {
                    return pFont;
                }
            }

            public bool Focused
            {
                get
                {
                    return pFocused;
                }
            }

            #endregion

        }

        #endregion

    }

}